(function($) {
	
	$.fn.checkPasswordStrength = function(options) {

		var defaults = {
			msgShort : "Your password is too short!",
			msgWeak : "Weak Password",
			msgFair : "Fair Password",
			msgGood : "Good Password",
			msgGreat : "Very Good Password",
			minLength : 8,
			weakPatterns : [ "12345678", "password", "p@ssw0rd" ],
			style : "psStyle"
		};
		var opts = $.extend(defaults, options);
		var obj = $(this);

		return this.each(function() {

			$(obj).unbind().keyup(
					function() {

						try {
							var results = $.fn.checkStrength(obj.val(), opts);

							$(this).next().remove();
							$(obj).after("<span class='" + opts.style + "'> " + results + "</span>");
							
						} catch (e) {
							alert(e);
						}

					});

			$.fn.checkStrength = function(password, options) {

				var isNum = false;
				var isCharLower = false;
				var isCharUpper = false;
				var isSymbols = false;
				var isLengthMeetMinRequirement = false;

				if (password.length >= options.minLength) {
					isLengthMeetMinRequirement = true;
				}

				if (password.match(/([0-9])/)) {
					isNum = true;
				}

				if (password.match(/([a-z])/)) {
					isCharLower = true;
				}

				if (password.match(/([A-Z])/)) {
					isCharUpper = true;
				}

				if (password.match(/([!,@,#,$,%,^,&,*,?,_,~,.,\,,;,=])/)) {
					isSymbols = true;
				}

				if (isLengthMeetMinRequirement) {

					//always override
					if ($.fn.isWeakPassword(password, options.weakPatterns, options.minLength - 2)) {
						return options.msgWeak;
					}
					
					if (isNum && isCharUpper && isCharLower && isSymbols) {
						return options.msgGreat; // best password
					}

					if (isNum && (isCharUpper || isCharLower) && isSymbols) {
						return options.msgGood;
					}

					if (isNum && (isCharUpper || isCharLower)) {
						return options.msgGood;
					}

					if (isNum && isSymbols) {
						return options.msgGood;
					}

					if ((isCharUpper || isCharLower) && isSymbols) {
						return options.msgGood;
					}

					// if all nums or chars or symbols only
					return options.msgFair;

				} else {
					return options.msgShort;
				}

			}// end of checkStrength

			$.fn.isWeakPassword = function(password, weakPatterns,
					repeatedTimeConsiderWeak) {

				for (var i=0; i< weakPatterns.length; i++) {

					if (password == weakPatterns[i]) {
						return true;
					}
					
				}

				// check repeated patterns
				var numOfRepeatedTime = 0;
				
				for ( var i = 0; i < password.length; i++) {
					
					if (i + 1 <= password.length) {

						if ((password.charAt(i)) == (password.charAt(i + 1))) {
							numOfRepeatedTime++;
						}
					}

					if (numOfRepeatedTime >= repeatedTimeConsiderWeak) {
						return true;
					}

				}

				return false;

			}// end of isWeakPassword

		}); //end of return this.each(function()

	};// end of testabc

})(jQuery);
